﻿
using Boilen.Primitives.Members;
using System.Collections.Generic;


namespace Boilen.Primitives.Implementers {

    /// <inheritdoc/>
    /// <summary>
    /// Implements a lazy property.
    /// </summary>
    public sealed class LazyProperty<T> : MutableProperty<T>
        where T : class {


        /// <summary>
        /// Gets the expression used to initialize the property.
        /// </summary>
        public string InitializerExpression { get; private set; }

        /// <inheritdoc/>
        protected override string FieldNamePrefix { get { return Property<T>.PropertyFieldNamePrefix; } }

        /// <inheritdoc/>
        protected override IEnumerable<InitializationMember> Initializers {
            get { yield break; }
        }

        /// <inheritdoc/>
        protected override AccessorMember Accessor {
            get {
                var accessor = base.Accessor;
                accessor.ObserveMember = this.CreateAccessorBlock( ObserveAccessorName, WriteAccessorBlock );
                return accessor;
            }
        }


        /// <inheritdoc/>
        public LazyProperty( PartialType parent, string name, string description, string initializerExpression )
            : base( parent, name, description ) {
            this.InitializerExpression = initializerExpression;
        }


        private void WriteAccessorBlock( ICodeWriter writer ) {
            writer.WriteLine( "if (object.ReferenceEquals(this.{0}, null))", this.FieldName );
            using( Enclose.Braces( writer ) )
                writer.WriteLine( "this.{0} = {1};", this.AccessorName, this.InitializerExpression );

            writer.WriteLine( );
            writer.WriteLine( "return this.{0};", this.FieldName );
        }

    }

}
